#include "../opcode.h"
#include "../service.h"

#include "gateway.h"

bool g_bIsRunning = false;

bool IsRunning()
{
	return g_bIsRunning;
}

void CloseGate()
{
	g_bIsRunning = false;
}

Gateway::Gateway()
: Connection(SOCKET_TYPE_TCP)
, m_state(STATE_NONE)
, m_ip(NULL)
{
	g_bIsRunning = true;

	m_serviceManager = SAFE_NEW ServiceManager(this);
}

Gateway::~Gateway()
{
	SAFE_DELETE_ARRAY(m_ip);
	SAFE_DELETE(m_serviceManager);
}

void Gateway::Init(vector<string>& configs)
{
	m_ip = StringNew("10.15.1.242");
	m_port = 8000;
	m_socket->Connect(m_ip, m_port);

	vector<string> params; params.clear();
	m_serviceManager->CallService(SERVICE_LOGIN, params);
}

int Gateway::Update()
{
	HandleSendSocket();
	HandleRecvSocket();
	HandleNetPacket();

	m_serviceManager->Update();

	switch(m_state)
	{
	case STATE_CLOSING_SERVICE:
		if(m_serviceManager->Empty())
			m_state = STATE_CLOSED;
		break;

	case STATE_CLOSED:
		g_bIsRunning = false;
		break;

	case STATE_RUN:
		break;

	default:
		break;
	}

	return 0;
}

bool Gateway::SendPacket()
{
	if(!m_sendQueue.IsEmpty())
	{
		NetPacket sendPacket;
		if(m_sendQueue.Dequeue(sendPacket) != 0)
			return false;

		bool success = Send((const char*)sendPacket.Data(), sendPacket.Size());
		if(success)
		{
			m_waitingQueue.Enqueue(sendPacket);
			return true;
		}
		else
			return false;
	}

	return true;
}

void Gateway::RecvPacket()
{
	Recv();
	ToNetPacket();
}

void Gateway::ToNetPacket()
{
	while(m_recvBuffer.length() >= NET_PACKET_OFFSET)
	{
		const char* data = m_recvBuffer.c_str();
		int lenData = m_recvBuffer.length();

		uint16 bodySize = 0;
		memcpy((uint8*)&bodySize, data, 2);
		bodySize = ntohs(bodySize);

		if(m_recvBuffer.length() >= bodySize)
		{
			NetPacket recvPacket;
			recvPacket.DecodePacket((const uint8*)data, bodySize);
			m_recvQueue.Enqueue(recvPacket);

			m_recvBuffer = m_recvBuffer.substr(bodySize);
		}
	}
}

bool Gateway::SendSelectPacket()
{
	if(send_select())
		return SendPacket();

	return false;
}

void Gateway::RecvSelectPacket()
{	
	RecvSelect();
	ToNetPacket();
}

int Gateway::HandleNetPacket()
{
	if(m_recvQueue.IsEmpty() && m_waitingQueue.IsEmpty()) return HANDLE_PACKET_NONE;

	NetPacket recvPacket;
	if(m_recvQueue.Dequeue(recvPacket) != 0)
		return HANDLE_PACKET_INVAILD;

	NetPacket waitingPacket;
	if(m_waitingQueue.Dequeue(waitingPacket) != 0)
		return HANDLE_PACKET_INVAILD;

	uint16 opcode = recvPacket.GetOpcode();
	if (sHanlderMap.count(opcode) == 0)
	{
		ELOG("Received unhandled opcode[0x%.4X : %s], uid[%s]", opcode, OPCODE2NAME(opcode), GetUid().c_str());
		return HANDLE_PACKET_NOREG_OPCODE;
	}

	try
	{
		if(sHanlderMap[opcode]->Execute(waitingPacket.GetRegister(), recvPacket) < 0)
			return HANDLE_PACKET_ERROR;
	}
	catch(...)
	{
		ELOG("Invalid packet format opcode[0x%.4X : %s], uid[%s]", opcode, OPCODE2NAME(opcode), GetUid().c_str());
		return HANDLE_PACKET_FORMAT_DONOT_MATCH;
	}

	return HANDLE_PACKET_NONE;
}

void Gateway::PushSendPacket(NetPacket& packet, BlockTree* tree)
{
	if(tree != NULL)
		tree->FillUpNetPacket(packet);

	packet.EncodePacket();

	m_sendQueue.Enqueue(packet);
}
